﻿namespace Webinator.Impls
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using Interfaces;

    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Reviewed. Suppression is OK here.")]
    internal abstract class LogUtil : ILogUtil
    {
        private readonly ICore _core;

        protected readonly IDictionary<string, string> LogsDictionary = new Dictionary<string, string>();

        protected int ScreenshotCounter;

        protected LogUtil(ICore core)
        {
            _core = core;
            ScreenshotCounter = 1;
            AddLog("Errors");
            AddLog("Verbose");
        }

        public void AddLog(string log)
        {
            if (!LogsDictionary.ContainsKey(log))
            {
                LogsDictionary.Add(log, string.Empty);
            }
        }

        public void Append(string log, string message)
        {
            string value;
            if (LogsDictionary.TryGetValue(log, out value))
            {
                value += string.Format("\r\n [{0}] {1}", DateTime.Now, message);
            }

            LogsDictionary[log] = value;

            if (_core.Config.LogRealTime)
            {
                SaveLogToDisc(log);
            }
        }

        public void ClearLog(string log)
        {
            string value;
            if (LogsDictionary.TryGetValue(log, out value))
            {
                LogsDictionary[log] = string.Empty;
            }
        }

        public abstract void DisplayMessageInBrowser(string message, int interval = 2500);

        public string GetLog(string log)
        {
            string value;
            LogsDictionary.TryGetValue(log, out value);

            return value;
        }

        public abstract void LogScreenshot();

        public void SaveAllLogsToDisc()
        {
            foreach (var key in LogsDictionary.Keys)
            {
                SaveLogToDisc(key);
            }
        }

        public void SaveLogToDisc(string log)
        {
            if (_core.Config.LogLevel == Config.AvailableLogLevels.None)
            {
                return;
            }

            var path = Path.Combine(_core.Config.LogDirectory, string.Format("{0}.txt", log));
            try
            {
                var body = LogsDictionary[log];
                File.Delete(path);
                var tw = new StreamWriter(path);

                tw.Write(body);
                tw.Close();
            }
            catch (Exception ex)
            {
                Append("Errors", string.Format("IO error writing [{0}] log to disc. Exception: {1}", log, ex));
            }
        }
    }
}